package com.hzit;

import com.sun.scenario.effect.impl.prism.ps.PPSBlend_ADDPeer;
import org.springframework.context.annotation.EnableLoadTimeWeaving;

import java.util.concurrent.*;

/**
 * 类名：
 * 作者：WF
 * 功能：
 */
public class TestThreadDemo {
	//0. 构造一个线程池对象
	private static ExecutorService pool =
			new ThreadPoolExecutor(10,20,
					0L, TimeUnit.MILLISECONDS,
					new LinkedBlockingQueue<Runnable>(),
					Executors.defaultThreadFactory(),
					new ThreadPoolExecutor.AbortPolicy());
	public static void main(String[] args) throws ExecutionException, InterruptedException {
		// test01();
		test03();
	}


	//1. 实现多线程的第三种方式，使用FutureTask,相比较实现Runnable接口与继承Thead类来说，此方式可以得到返回值
	private static void test01() throws ExecutionException, InterruptedException {
		FutureTask<Integer> task = new FutureTask<>(new Callable<Integer>() {
			@Override
			public Integer call() throws Exception {
				return 10 / 2;
			}
		});
		new Thread(task).start();
		Integer rs = task.get();
		System.out.println("rs = " + rs);
	}

	//2. 创建线程池的方式
	private static void test02(){
		ExecutorService executorService = Executors.newFixedThreadPool(10);

	}
	//3. 创建异步对象,执行异步任务
	private static void test03() throws ExecutionException, InterruptedException {
		//3.1 Runnable接口，没有输入参数及返回值
		CompletableFuture<Void> future1 = CompletableFuture.runAsync(() -> {
			System.out.println("线程一正在执行.");
		}, pool);
		//3.2 没有输入参数有返回值
		CompletableFuture<Integer> future2 = CompletableFuture.supplyAsync(() -> {
			return 10 / 0;
		},pool);
		// Integer rs = future2.get();
		// System.out.println("rs = " + rs);

		//3.3 参数1：代表上次返回值（有异常没有返回值），参数2：上次执行结果中的异常
		// CompletableFuture<Integer> future3 = future2.whenCompleteAsync((t, e) -> {
		// 	System.out.println("上次返回值：" + t);
		// 	System.out.println("异常信息：" + e);
		// }, pool);

		//3.4 对异常进行处理，处理成你需要的结果。
		CompletableFuture<Integer> future4 = future2.exceptionally(t -> {
			try {
				Thread.sleep(5000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			return 5;
		});
		Integer rs2 = future4.get();
		System.out.println("rs2 = " + rs2);

		//3.5 参数t:上次返回结果 参数e：代表上面任务抛出的异常 返回值：就是我们想处理的结果
		CompletableFuture<Integer> future5 = future2.handleAsync((t, e) -> {
			System.out.println("异常信息：" + e.getMessage());
			return 8;
		}, pool);
		Integer rs3 = future5.get();
		System.out.println("rs3 = " + rs3);

		//3.6 串行化
		//3.6.1 无输入和输出的参数
		CompletableFuture<Void> future6 = future5.thenRunAsync(() -> {
			System.out.println("任务五执行完成，该任务六执行了。");
		}, pool);
		//3.6.2 有输入无输出参数
		CompletableFuture<Void> future7 = future5.thenAcceptAsync(t -> {
			System.out.println("任务七执行：任务五的返回值 ： " + t);
		}, pool);
		//3.6.3 有输入有输出参数
		CompletableFuture<Integer> future8 = future5.thenApplyAsync(r -> {
			System.out.println("任务八执行：将任务五的结果乘以3并返回");
			return r * 3;
		}, pool);
		Integer rs4 = future8.get();
		System.out.println("rs4 = " + rs4);

		//3.7 多任务组合 (两个任务都完成，才处理当前任务)
		//3.7.1 有输入参数（上个任务返回结果）、异常信息、返回值
		System.out.println("-------------------------------------------------------------");
		CompletableFuture<Integer> future9 = future5.thenCombineAsync(future8, (t, e) -> {
			System.out.println("上次的结果是：" + t);
			return t - 10;
		}, pool);
		// Integer rs5 = future9.get();
		// System.out.println("rs5 = " + rs5);
		System.out.println("-------------------------------------------------------------");

		//3.7.2 有输入参数（上个任务返回结果）、异常信息、无返回值
		// CompletableFuture<Void> future10 = future5.thenAcceptBothAsync(future9, (t, u) -> {
		// 	System.out.println("任务10：上次的结果：" + t);
		// }, pool);

		//3.8 多任务组合 (两个任务只要有一个完成就处理当前任务)
		CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
			try {
				Thread.sleep(10000);
				System.out.println("我正在休息。。。");
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			return 1;
		},pool);
		CompletableFuture<Void> future11 = future.acceptEitherAsync(future9, r -> {
			System.out.println("任务4与任务9只要有一个完成就处理当前任务.");
		}, pool);

		//3.9 多任务组合
		//3.9.1 多个任务只要有一个完成就结束
		CompletableFuture.anyOf(future5, future).get();
		//3.9.2 多个任务全部完成才可以结束
		CompletableFuture<Void> future12 = CompletableFuture.allOf(future4, future11);
		future12.get();
		System.out.println("任务4与任务11执行完成。");
	}

}
